		TITLE	STACK - Copyright (c) SLR Systems 1994

		INCLUDE	MACROS
		INCLUDE	SYMBOLS
		INCLUDE	SEGMENTS
		INCLUDE	GROUPS
		INCLUDE	MODULES
		INCLUDE	CLASSES
if	fg_pe
		INCLUDE	EXES
endif

		PUBLIC	DEFINE_STACK_SEGMENT,DEFINE_DOSSEG_SYMBOLS,_END_GINDEX,PUT_EAX_IN_DGROUP,__END_GINDEX


		.DATA

		EXTERNDEF	SEG_COMBINE:BYTE,PUB_SIZE:BYTE,PUB_TYPE:BYTE,SEG32_FLAGS:BYTE,SYMBOL_TEXT:BYTE,SEG_ALIGN:BYTE

		EXTERNDEF	END_OF_RECORD:DWORD,FLAG_0C:DWORD,SYMBOL_HASH:DWORD,CLASS_NAME_LINDEX:DWORD,SEG_NAME_LINDEX:DWORD
		EXTERNDEF	PUB_GROUP_GINDEX:DWORD,ICODE_SEGMOD_GINDEX:DWORD,CURNMOD_GINDEX:DWORD,FIRST_STACK_GINDEX:DWORD
		EXTERNDEF	PUB_SEGMOD_GINDEX:DWORD,MOD_FIRST_PUBLIC_GINDEX:DWORD,DGROUP_GINDEX:DWORD,STACK_DELTA:DWORD
		EXTERNDEF	SEG_LEN:DWORD,STACK_SIZE:DWORD,STACK_COMMIT:DWORD,SYMBOL_LENGTH:DWORD,FIRST_MODULE_GINDEX:DWORD
		EXTERNDEF	FIRST_IMPMOD_GINDEX:DWORD,IDATA_SEGMOD_GINDEX:DWORD,FIRST__IMP__GINDEX:DWORD

		EXTERNDEF	BSS_TPTR:TPTR_STRUCT,STACK_TPTR:TPTR_STRUCT,DGROUP_TPTR:TPTR_STRUCT,ICODE_TPTR:TPTR_STRUCT
		EXTERNDEF	IMP__DATA_TPTR:TPTR_STRUCT

		EXTERNDEF	SEGMENT_GARRAY:STD_PTR_S,SEGMOD_GARRAY:STD_PTR_S,MODULE_GARRAY:STD_PTR_S,IMPMOD_GARRAY:STD_PTR_S

		EXTERNDEF	EXEHEADER:EXE,NEXEHEADER:NEXE,PEXEHEADER:PEXE


		.CODE	MIDDLE_TEXT

		EXTERNDEF	WARN_RET:PROC,PUB_CHECK:PROC,INSTALL_GROUP_SYMBOL:PROC,DEFINE_SEGMOD:PROC,PUT_SM_IN_GROUP:PROC
		EXTERNDEF	LDATA_ALLOC:PROC,SEARCH_CLASS_SYMBOL:PROC,MAKE_TPTR_LINDEX:PROC,GET_SM_MODULE:PROC
		EXTERNDEF	DEFINE_SEGMOD_0:PROC,INIT_LOCAL_STORAGE:PROC,RELEASE_LOCAL_STORAGE:PROC

		EXTERNDEF	MISSING_STACK_ERR:ABS


PUT_EAX_IN_DGROUP	PROC
		;
		;
		;
		PUSHM	EDI,ESI

		MOV	ESI,OFF DGROUP_TPTR._TP_TEXT
		PUSH	EAX

		MOV	EDX,DGROUP_TPTR._TP_HASH
		MOV	ECX,DGROUP_TPTR._TP_LENGTH

		MOV	SYMBOL_HASH,EDX
		MOV	SYMBOL_LENGTH,ECX

		SHR	ECX,2
		MOV	EDI,OFF SYMBOL_TEXT

		INC	ECX

		REP	MOVSD

		CALL	INSTALL_GROUP_SYMBOL	;EAX IS GINDEX, ECX IS GROUP

		MOV	CL,[ECX].GROUP_STRUCT._G_TYPE
		MOV	EDX,EAX

		POPM	EAX,ESI

		POP	EDI
		JMP	PUT_SM_IN_GROUP		;EDX=GROUP_MINDEX, ECX=G_TYPE, EAX=SEGMOD_MINDEX

PUT_EAX_IN_DGROUP	ENDP

if	fg_pe

CREATE_IDATA	PROC

		MOV	EAX,OFF IMP__DATA_TPTR
		JMP	CI_1

CREATE_IDATA	ENDP


CREATE_ICODE	PROC	NEAR
		;
		;
		;
		MOV	EAX,OFF ICODE_TPTR
CI_1::
		MOV	ECX,FIRST_MODULE_GINDEX

		MOV	CURNMOD_GINDEX,ECX
		CALL	MAKE_TPTR_LINDEX

		MOV	CLASS_NAME_LINDEX,EAX
		MOV	SEG_NAME_LINDEX,EAX
		;
		MOV	AL,5			;DWORD ALIGNMENT
		MOV	CL,MASK SEG32_USE32

		MOV	SEG_ALIGN,AL
		MOV	EAX,2
		
		MOV	SEG32_FLAGS,CL
		MOV	SEG_LEN,EAX

		MOV	SEG_COMBINE,AH	;WORD PRIVATE
		CALL	DEFINE_SEGMOD		;AX IS SEGMOD, DS:BX IS PHYS

		MOV	CURNMOD_GINDEX,0

		RET

CREATE_ICODE	ENDP

endif


CREATE_BSS	PROC	NEAR
		;
		;
		;
		MOV	EAX,OFF BSS_TPTR
		JMP	CREATE_MINI_SEGMENT

CREATE_BSS	ENDP

CREATE_STACK	PROC	NEAR
		;
		;
		;
		MOV	EAX,OFF STACK_TPTR
CREATE_MINI_SEGMENT::

		MOV	ECX,FIRST_MODULE_GINDEX

		MOV	CURNMOD_GINDEX,ECX
		CALL	MAKE_TPTR_LINDEX

		MOV	CLASS_NAME_LINDEX,EAX
		MOV	SEG_NAME_LINDEX,EAX
		;
		MOV	WPTR SEG_COMBINE,100H	;BYTE PRIVATE
		MOV	SEG32_FLAGS,0		;DON'T FORCE USE16/USE32
		CALL	DEFINE_SEGMOD_0		;EAX IS SEGMOD, ECX IS PHYS

		CALL	PUT_EAX_IN_DGROUP	;USE16/USE32 MAY BE FORCED BY OTHER SEGMENTS IN DGROUP

		XOR	EAX,EAX
		MOV	CURNMOD_GINDEX,EAX
		RET

CREATE_STACK	ENDP


DEFINE_STACK_SEGMENT	PROC
		;
		;DOESN'T REALLY ADD IT, JUST DEFINES IT...
		;
		MOV	EAX,FIRST_STACK_GINDEX

		TEST	EAX,EAX
		JZ	MIS_STK
L1$:
		RET

MIS_STK:
		;
		;NO STACK, SHALL WE DEFINE ONE?
		;
if	fg_segm OR fg_pe
		TEST	FLAG_0C,MASK APPTYPE	;NO STACK REQUIRED FOR LIBRARY
		JNZ	L1$
endif
		BITT	STACK_SIZE_FLAG		;DID WE SPECIFY A SIZE?
		JNZ	DECLARE_STACK
if	fg_norm_exe
		BITT	OUTPUT_COM_SYS		;NO STACK NEEDED FOR COM OR SYS FILES
		JNZ	L1$
endif


if	fg_rom
		BITT	OUTPUT_ABS		;NO STACK REQUIRED FOR HEX OUTPUT
		JNZ	L1$
endif

if	fg_pe
		BITT	OUTPUT_PE
		JNZ	L4$
endif
		MOV	AL,MISSING_STACK_ERR	;REALLY SHOULD HAVE HAD A STACK
		CALL	WARN_RET
		RET

if	fg_pe
L4$:
		MOV	STACK_SIZE,100000H	;DEFAULT IS 1 MEGABYTE
		MOV	PEXEHEADER._PEXE_STACK_COMMIT,8K
		RET

endif

DECLARE_STACK:

if	fg_pe
		BITT	OUTPUT_PE
		JZ	L59$
		RET


L59$:

endif

		;
		;OK, WE ARE CREATING A DUMMY STACK SEGMENT...
		;DECLARE A SEGMENT STACK SEGMENT DWORD STACK 'STACK'
		;OF STACK_SIZE LENGTH
		;
		;IF DOSSEG, STICK IT IN DGROUP...
		;
		CALL	INIT_LOCAL_STORAGE
		MOV	ECX,FIRST_MODULE_GINDEX
		MOV	EAX,OFF STACK_TPTR

		MOV	CURNMOD_GINDEX,ECX
		CALL	MAKE_TPTR_LINDEX

		MOV	CLASS_NAME_LINDEX,EAX
		MOV	SEG_NAME_LINDEX,EAX
		;
		MOV	WPTR SEG_COMBINE,505H	;DWORD STACK

		MOV	SEG32_FLAGS,0		;DON'T FORCE USE16/USE32
		MOV	EAX,STACK_SIZE
		MOV	SEG_LEN,EAX

		CALL	DEFINE_SEGMOD		;EAX IS SEGMOD, ECX IS PHYS

if	fg_segm
		BITT	OUTPUT_SEGMENTED	;SEGMENTED OUTPUT ALWAYS GOES IN DGROUP
		JNZ	L01$
endif
		BITT	DOSSEG_FLAG		;DOSSEG OUTPUT ALWAYS GOES IN DGROUP
		JZ	DS_NOT_DGROUP
L01$:
		CALL	PUT_EAX_IN_DGROUP
DS_NOT_DGROUP:
		XOR	EAX,EAX

		MOV	CURNMOD_GINDEX,EAX
		CALL	RELEASE_LOCAL_STORAGE

		RET

DEFINE_STACK_SEGMENT	ENDP


DEFINE_DOSSEG_SYMBOLS	PROC
		;
		;
		;
		CALL	INIT_LOCAL_STORAGE	;FOR SEGMENT AND CLASS NAMES...

if	fg_pe

		BITT	OUTPUT_PE
		JZ	L1$
		CMP	FIRST_IMPMOD_GINDEX,0
		JZ	L1$
		CALL	CREATE_ICODE
		MOV	ICODE_SEGMOD_GINDEX,EAX
L1$:
		CMP	FIRST__IMP__GINDEX,0
		JZ	L2$
		CALL	CREATE_IDATA
		MOV	IDATA_SEGMOD_GINDEX,EAX
L2$:		

endif

		BITT	DOSSEG_FLAG
		JZ	L9$
		CMP	DGROUP_GINDEX,0		;SKIP IF NO DGROUP
		JZ	L9$

		;OK, _end IS DGROUP:STACK

		MOV	EAX,OFF _EDATA_STUFF
		CALL	DO_DOSSEG_DEFINE

		MOV	EAX,OFF __EDATA_STUFF
		CALL	DO_DOSSEG_DEFINE

		MOV	EAX,OFF _END_STUFF
		CALL	DO_DOSSEG_DEFINE

		MOV	EAX,OFF __END_STUFF
		CALL	DO_DOSSEG_DEFINE
L9$:
		CALL	RELEASE_LOCAL_STORAGE
		RET

DEFINE_DOSSEG_SYMBOLS	ENDP


NO_BSS:
		POPM	EAX,ESI,EDI
		PUSH	EAX

		CALL	DPTR [EAX-4]

		POP	EAX

DO_DOSSEG_DEFINE	PROC	NEAR
		;
		; DEFINE SEG_CLASS_NAME, SEG_NAME, SEG_COMBINE, SEG_ALIGN
		;
		PUSHM	EDI,ESI

		MOV	ESI,[EAX]
		ASSUME	ESI:PTR TPTR_STRUCT
		MOV	EDI,OFF SYMBOL_TEXT

		MOV	EDX,[ESI]._TP_HASH
		MOV	ECX,[ESI]._TP_LENGTH

		MOV	SYMBOL_HASH,EDX
		MOV	SYMBOL_LENGTH,ECX

		SHR	ECX,2
		LEA	ESI,[ESI]._TP_TEXT

		INC	ECX
		REP	MOVSD

		PUSH	EAX
		CALL	SEARCH_CLASS_SYMBOL		;AX IS INDEX, DS:BX IS PHYS

		JC	NO_BSS
		;
		;GET FIRST SEGMENT
		;
		MOV	EAX,[ECX].CLASS_STRUCT._C_FIRST_SEG_GINDEX
L2$:
		TEST	EAX,EAX
		JZ	NO_BSS

		CONVERT	EAX,EAX,SEGMENT_GARRAY
		ASSUME	EAX:PTR SEGMENT_STRUCT

		MOV	ECX,[EAX]._SEG_GROUP_GINDEX
		MOV	EDX,DGROUP_GINDEX

		CMP	EDX,ECX
		JZ	L4$
L3$:
		;
		;NOPE, TRY NEXT SEG
		;
		MOV	EAX,[EAX]._SEG_NEXT_SEG_GINDEX
		JMP	L2$


L4$:
		MOV	EAX,[EAX]._SEG_FIRST_SEGMOD_GINDEX

		TEST	EAX,EAX
		JZ	NO_BSS

		MOV	PUB_SEGMOD_GINDEX,EAX
		MOV	PUB_GROUP_GINDEX,EAX		;SET USE_GROUP

		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

		CALL	GET_SM_MODULE

		MOV	CURNMOD_GINDEX,EAX
		CONVERT	EAX,EAX,MODULE_GARRAY
		ASSUME	EAX:PTR MODULE_STRUCT
		MOV	EAX,[EAX]._M_FIRST_PUB_GINDEX

		MOV	PUB_SIZE,0

		MOV	MOD_FIRST_PUBLIC_GINDEX,EAX
		POP	EAX

		MOV	PUB_TYPE,NSYM_RELOC

		MOV	ESI,DPTR [EAX+4]
		PUSH	EAX

		XOR	ECX,ECX

		MOV	CL,BYTE PTR[ESI]

		LEA	EAX,[ECX+ESI+4]

		MOV	END_OF_RECORD,EAX
		CALL	PUB_CHECK		;PROCESS IT...

		MOV	EAX,CURNMOD_GINDEX
		POP	EDX

		XOR	ESI,ESI
		MOV	ECX,MOD_FIRST_PUBLIC_GINDEX

		CONVERT	EAX,EAX,MODULE_GARRAY
		ASSUME	EAX:PTR MODULE_STRUCT

		MOV	CURNMOD_GINDEX,ESI
		MOV	[EAX]._M_FIRST_PUB_GINDEX,ECX

		MOV	[EDX+8],ECX		;DEFINE POINTER...

		POPM	ESI,EDI

		RET

DO_DOSSEG_DEFINE	ENDP

if	fg_rom
		PUBLIC	DEFINE_STARTUP

DEFINE_STARTUP	PROC
		;
		;DEFINE A SEGMOD FOR STARTUP:STARTUP, USE LENGTH AS 12*# OF
		;LINKS
		;
		FIXDS
		FIXES
		LEA	SI,FIRST_MODULE
		LEA	DI,CURNMOD
		MOVSW
		MOVSW

		LEA	SI,STARTUP_PTR
		LEA	DI,SEG_CLASS_NAME
		MOVSW
		MOVSW
		;
		LEA	SI,STARTUP_PTR
		LEA	DI,SEG_NAME
		MOVSW
		MOVSW
		;
		MOV	WPTR SEG_COMBINE,102H	;BYTE PUBLIC
		MOV	AX,TARGET_COUNT
		MOV	BX,12
		MUL	BX
		ADD	AX,2
		ADC	DX,0
		MOV	SEG_LEN.LW,AX
		MOV	SEG_LEN.HW,DX
		MOV	SEG32_FLAGS,0
		CALL	DEFINE_SEGMOD		;AX:BX IS SEGMOD, DX IS PHYS
		ASSUME	DS:NOTHING

		MOV	TARGET_SEGMOD.OFFS,BX
		MOV	TARGET_SEGMOD.SEGM,AX
		MOV	DS,DX
		MOV	AL,[BX]._SM_FLAGS
		MOV	CLASS_TYPE,AL
		MOV	AX,SIZE LDATA_HEADER_TYPE
		MOV	CX,SEG_LEN.LW
		ADD	AX,CX
SPEC_RET:
		PUSH	AX
		XOR	DX,DX		;NO SECOND BLK
		CALL	LDATA_ALLOC	;AX=BLK#,BX=LOG, ES:DI=PHYS
		JC	SPECIAL
		POP	AX
		MOV	TARGET_DATA.OFFS,DI
		MOV	TARGET_DATA.SEGM,BX
SPEC_2:
		;
		;NEXT_LDATA
		;TYPE
		;SECOND_BLK
		;LENGTH
		;OFFSET
		;
		XOR	AX,AX
		STOSW			;PTR TO NEXT = 0
		STOSW
		MOV	AL,MASK BIT_LE	;LEDATA 16 BIT
		STOSW			;TYPE
		XOR	AX,AX
		STOSW			;SECOND_BLK (USUALLY ZERO)
		MOV	AX,CX
		STOSW			;STORE # OF DATA BYTES IN RECORD
		XOR	AX,AX
		STOSW			;OFFSET
		STOSW			;32-BITS WORTH
		MOV	AX,TARGET_COUNT
		STOSW
		SUB	CX,2
		XOR	AX,AX
		MOV	TARGET_OFFSET,DI
		OPTI_STOSB		;ZERO OUT REST OF RECORD
		;
		;NOW, LINK THIS TO SEGMOD
		LDS	SI,TARGET_SEGMOD;DS:SI IS SEGMOD
		SYM_CONV_DS
		LES	DI,TARGET_DATA
		MOV	DS:[SI]._SM_FIRST_DAT.OFFS,DI
		MOV	DS:[SI]._SM_FIRST_DAT.SEGM,ES
		MOV	[SI]._SM_LAST_DAT.OFFS,DI
		MOV	[SI]._SM_LAST_DAT.SEGM,ES
		MOV	CURNMOD.SEGM,0
		RET

SPECIAL:
		POP	AX
		DEC	ES:WPTR 0			;DON'T COUNT THAT GUY
		JMP	SPEC_RET

DEFINE_STARTUP	ENDP

endif

		.DATA

		ALIGN	4

		DD	CREATE_BSS			;SEGMENT TO CREATE IF MISSING
_EDATA_STUFF	DD	BSS_TPTR			;SEGMENT THIS SYMBOL EQUATES TO
		DD	_EDATA_TEXT
_EDATA_GINDEX	DD	0

		DD	CREATE_BSS			;SEGMENT TO CREATE IF MISSING
__EDATA_STUFF	DD	BSS_TPTR
		DD	__EDATA_TEXT
__EDATA_GINDEX	DD	0

		DD	CREATE_STACK
_END_STUFF	DD	STACK_TPTR
		DD	_END_TEXT
_END_GINDEX	DD	0

		DD	CREATE_STACK
__END_STUFF	DD	STACK_TPTR
		DD	__END_TEXT
__END_GINDEX	DD	0

_EDATA_TEXT	DB	6,'_edata',0,0,0		;LOOKS LIKE PUBDEF RECORD...
__EDATA_TEXT	DB	7,'__edata',0,0,0
_END_TEXT	DB	4,'_end',0,0,0
__END_TEXT	DB	5,'__end',0,0,0

		END

